/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.murillo.chufa.datastructures;
import org.murillo.chufa.entry.WeakKey;
import java.lang.ref.ReferenceQueue;
import java.util.HashMap;
import java.util.LinkedList;

/**
 *
 * @author Administrador
 */
public class WeakFifoBoundedBag<K> extends BoundedBag<K>{

   HashMap<WeakKey<K>, Counter> ocurrenceMap;
   LinkedList<WeakKey<K>> valueList;
   ReferenceQueue deadKeys = new ReferenceQueue();

   public WeakFifoBoundedBag(int maxsize) {
      super(maxsize);
      this.ocurrenceMap = new HashMap<WeakKey<K>, Counter>(maxsize / 2);
      this.valueList = new LinkedList<WeakKey<K>>();
   }

   public void remove(K k) {
      WeakKey<K> mock = new WeakKey<K>(k);
      Counter c = ocurrenceMap.get(mock);
      if (c != null) {
         int count = c.remove();
         if (count <= 0) {
            ocurrenceMap.remove(mock);
         }
         valueList.removeLastOccurrence(mock);
      }
   }

   public void add(K k) {
      WeakKey<K> mock = new WeakKey<K>(k);
      if (valueList.size() >= maxsize) {
         K last = valueList.getLast().getKey();
         remove(last);
      }
      Counter c = ocurrenceMap.get(mock);
      if (c == null) {
         c = new Counter();
         mock = new WeakKey<K>(k, deadKeys, null);
         ocurrenceMap.put(mock, c);
      }
      c.add();
      valueList.add(mock);
   }

   public boolean contains(K k) {
      if (k == null) {
         return false;
      }
      WeakKey<K> mock = new WeakKey<K>(k);
      return ocurrenceMap.containsKey(mock);
   }

   public void runMaintenance() {
      WeakKey<K> dead = (WeakKey<K>) deadKeys.poll();
      while (dead != null) {
         ocurrenceMap.remove(dead);
         while (valueList.remove(dead));
         dead = (WeakKey<K>) deadKeys.poll();
      }
   }

    @Override
    public void clear() {
        ocurrenceMap.clear();
        valueList.clear();
        deadKeys = new ReferenceQueue();
    }
}
